package com.magic.shop.util;

import cn.hutool.core.date.DateUtil;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.ssssssss.script.annotation.Comment;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 阿里云OSS上传文件工具类
 */
public class AlOssUtils {

    private static final Logger log = LoggerFactory.getLogger(AlOssUtils.class);

    //oss配置
    private static String accessKeyId = "LTAI4FvLQ4ThvLN1njW3UTgW";
    private static String accessKeySecret = "5Iwfyc9S1jsiX7srF7jnqg98fDlGbo";
    //域名
    private static String endpoint = "oss-cn-hangzhou.aliyuncs.com";
    //空间名
    private static String bucketName = "txlcoss-test";





    public final static String OOS_SEARCH_SIGN = "aliyuncs";
    public final static String PROTOCOL_STR = "https://";

    //保存的目录
    private static String directory = "resource1";
    //private static String endpointServer = "oss-cn-hangzhou.aliyuncs.com";

    public static void main(String[] args) {
//        File file = new File("/Users/xianshengzhang/Downloads/test/" + "png1img.png");
//
        String accessKeyId = "LTAI4FvLQ4ThvLN1njW3UTgW";
        String accessKeySecret = "5Iwfyc9S1jsiX7srF7jnqg98fDlGbo";
//        //域名
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
//        //空间名
//        String bucketName = "txlcoss-test";
//        //String name = file.getName();
//        Map<String, Object> map = upload(file, endpoint, accessKeyId, accessKeySecret, bucketName);
//
//        System.out.println(map);

        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
        listObjectsRequest.setPrefix("aliyuncs/*/sh_video");
        listObjectsRequest.setDelimiter("/");
        listObjectsRequest.setBucketName("receiving-test");

//        listObjectsRequest.setMarker("aliyuncs/1003/sh_video/2024/08/23/e7ec05f6389e4a8e83213a717f120bbc.mp4");
        listObjectsRequest.setMaxKeys(1000);

        // oss结果
        ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);


        // 列表
        objectListing.getObjectSummaries();

        String nextMarker = objectListing.getNextMarker();

        // 是否被截断
        boolean truncated = objectListing.isTruncated();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        if (truncated){
            System.out.println("还有其他的数据未查出");
            System.out.println("下一个文件："+nextMarker);
        }

        System.out.println("====================================================");

        for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
            System.out.println(objectSummary.getKey()+"    "+sdf.format(objectSummary.getLastModified()));
        }

        ossClient.shutdown();
//        Date uploadDate = new Date();
//        System.out.println(DateUtil.format(uploadDate,"yyyy/MM/dd"));
        // 1、插入到资源表
        /*PubResource pubResource = new PubResource();
        pubResource.setRsTitle(fileTitle);
        pubResource.setRsSuffix(suffix);
        pubResource.setRsType(FileUtils.getFileTypeBySuffix(suffix));
        pubResource.setRsUsrid(userId);
        pubResource.setRsUserBelongType(belongType);
        pubResource.setRsCreatetime(uploadDate);
        pubResource.setRsSize(fileSize);

        //插入图片hash值
        String rsHashValue=FileUploadUtils.getMD5Hash(file.getInputStream());
        pubResource.setRsHashValue(rsHashValue);
        pubResource.setRsServerUrl(getBucketDomain());

        // 3、更新文件信息、如果是图片要记录宽和高
        PubResource updateRes = new PubResource();
        updateRes.setRsId(pubResource.getRsId());
        //oss point 4
        updateRes.setRsMemo(reMemo);
        updateRes.setRsWidth(bufferedImage.getWidth());
        updateRes.setRsHeight(bufferedImage.getHeight());*/
    }


    // 所有图片扩展名
    public static final String SUFFIXPIC = "bmp,jpg,tiff,gif,pcx,tga,exif,fpx,svg,psd,cdr,pcd,dxf,ufo,eps,ai,raw,png";
    // 所有文档扩展名
    public static final String SUFFIXDOC = "txt,pdf,doc,docx,xls,ppt";
    // 所有视频扩展名
    public static final String SUFFIXVID = "avi,asf,wmv,avs,flv,mkv,mov,3gp,mp4,mpg,mpeg,dat,dsm,ogm,vob,rm,rmvb,ts,tp,ifo,nsv";
    // 所有声音扩展名
    public static final String SUFFIXSOD = "mp3,aac,wav,wma,cda,flac,m4a,mid,mka,mp2,mpa,mpc,ape,ofr,ogg,ra,wv,tta,ac3,dts,wv,shn,vqf,spc,nsf,adx,psf,minipsf,psf2,minipsf2,rsn,zst";
    // 所有falsh扩展名
    public static final String SUFFIXFLS = "swf,fla";

    // 图片类
    public static final int TYPE_PIC = 1;
    // 文档类
    public static final int TYPE_DOC = 2;
    // 视频类
    public static final int TYPE_VID = 3;
    // 声音类
    public static final int TYPE_SOD = 4;
    // falsh类
    public static final int TYPE_FLS = 5;
    // 其他类
    public static final int TYPE_OTH = 6;

    /**
     * 根据文件后缀获取文件类型
     *
     * @param suffix
     * @return 1：图片类 2：文档类 3:视频类 4:声音类 5:falsh类 6:其他类
     */
    public static int getFileTypeBySuffix(String suffix) {
        if (SUFFIXPIC.indexOf(suffix) >= 0) {// 图片
            return TYPE_PIC;
        } else if (SUFFIXDOC.indexOf(suffix) >= 0) {// 文档
            return TYPE_DOC;
        } else if (SUFFIXVID.indexOf(suffix) >= 0) {// 视频
            return TYPE_VID;
        } else if (SUFFIXSOD.indexOf(suffix) >= 0) {// 音频
            return TYPE_SOD;
        } else if (SUFFIXFLS.indexOf(suffix) >= 0) {// Flash
            return TYPE_FLS;
        } else {// 其他
            return TYPE_OTH;
        }
    }
    public static Map<String, Object> uploadFile(MultipartFile file) throws Exception {

        long fileSize = file.getSize();
        // 原始文件名
        String oriFileName = file.getOriginalFilename().trim();

        // 文件名，不包含后缀
        String fileTitle = oriFileName.substring(0, oriFileName.lastIndexOf('.'));
        // 文件名后缀
        String suffix = oriFileName.substring(oriFileName.lastIndexOf('.') + 1, oriFileName.length()).toLowerCase();
        // 存储路径
        String realPath = JarResourceUtil.getRootRealPath("upload-file");
        Date uploadDate = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String filePath = "/resource/" + formatter.format(uploadDate) + "/";


        // 2、保存文件到指定路径
        File dir = new File(realPath + filePath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String newFilePath = realPath + filePath + oriFileName;
        File newFile = new File(newFilePath);

        try{


            String errMsg = null;
            try {
                file.transferTo(newFile);
            } catch (IOException e) {
                e.printStackTrace();
                errMsg = e.toString();
            }
            Map<String, Object> map = upload(newFile, endpoint, accessKeyId, accessKeySecret, bucketName);
            map.put("fileSize", fileSize);
            map.put("rsTitle", fileTitle);
            if (errMsg != null) {
                map.put("errMsg", errMsg);
            }
            return map;
        }finally {
            //删除本地文件和文件夹
            File folder = new File(realPath );
            FileUtils.delete(folder);

        }
    }

    /**
     * 上传文件到阿里云oss
     *
     * @param file            文件
     * @param endpoint        域名
     * @param accessKeyId     秘钥id
     * @param accessKeySecret 秘钥
     * @param bucketName      空间名
     * @return
     */
    public static Map<String, Object> upload(MultipartFile file, String endpoint, String accessKeyId, String accessKeySecret, String bucketName) throws Exception {
        long fileSize = file.getSize();
        // 原始文件名
        String oriFileName = file.getOriginalFilename().trim();

        // 文件名，不包含后缀
        String fileTitle = oriFileName.substring(0, oriFileName.lastIndexOf('.'));
        // 文件名后缀
        String suffix = oriFileName.substring(oriFileName.lastIndexOf('.') + 1, oriFileName.length()).toLowerCase();
        // 存储路径
        String realPath = JarResourceUtil.getRootRealPath("upload-file");
        Date uploadDate = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        String filePath = "/resource/" + formatter.format(uploadDate) + "/";


        // 2、保存文件到指定路径
        File dir = new File(realPath + filePath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        String newFilePath = realPath + filePath + oriFileName;
        File newFile = new File(newFilePath);
        String errMsg = null;
        try {
            file.transferTo(newFile);
        } catch (IOException e) {
            e.printStackTrace();
            errMsg = e.toString();
        }
        Map<String, Object> map = upload(newFile, endpoint, accessKeyId, accessKeySecret, bucketName);
        map.put("fileSize", fileSize);
        map.put("rsTitle", fileTitle);
        if (errMsg != null) {
            map.put("errMsg", errMsg);
        }
        return map;
    }

    /**
     * 上传文件到阿里云oss
     *
     * @param file            文件
     * @param endpoint        域名
     * @param accessKeyId     秘钥id
     * @param accessKeySecret 秘钥
     * @param bucketName      空间名
     * @return
     */
    public static Map<String, Object> upload(File file, String endpoint, String accessKeyId, String accessKeySecret, String bucketName) {
        String oldFileName = file.getName();
        String newFileName = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        String suffix = null;
        if (oldFileName.indexOf(".") != -1) {
            String[] split = oldFileName.split("\\.");
            if (split.length > 1) {
                suffix = split[1];
                newFileName = newFileName + "." + split[1];
            }
        }
        //long fileSize = file.getSize();
        int rsType = 6;
        if (suffix != null) {
            rsType = getFileTypeBySuffix(suffix);
        }
        Date uploadDate = new Date();
        String filePath = OOS_SEARCH_SIGN + "/" + directory + "/" + DateUtil.format(uploadDate,"yyyy/MM/dd") + "/";
        String reMemo = filePath + newFileName;
        Map<String, Object> data = upload(file, reMemo, endpoint, accessKeyId, accessKeySecret, bucketName);
        String bucketDomain = getBucketDomain(bucketName, endpoint);
        String url = bucketDomain + reMemo;
        data.put("oldFileName", oldFileName);
        data.put("newFileName", newFileName);
        data.put("suffix", suffix);
        data.put("rsType", rsType);
        data.put("rsServerUrl", bucketDomain);
        data.put("reMemo", reMemo);
        data.put("url", url);
        return data;
    }

    public static Map<String, String> contentTypeMap = new HashMap<String, String>() {{
        put("pdf", "application/pdf");
        put("txt", "text/plain");
        put("mp4", "video/mpeg4");
        put("mp3", "audio/mp3");
        put("jpe", "image/jpeg");
        put("jpeg", "image/jpeg");
        put("jpg", "image/jpeg");
        put("png", "image/png");
    }};

    public static ObjectMetadata getContentType(String fileName) {
        ObjectMetadata meta = new ObjectMetadata();
        if (fileName == null) {
            return null;
        }
        if (fileName.indexOf(".") == -1) {
            return null;
        }
        String[] split = fileName.split("\\.");
        if (split.length < 2) {
            return null;
        }
        String key = split[split.length - 1];
        String contentType = contentTypeMap.get(key);
        if (contentType == null) {
            return null;
        }
        meta.setContentType(contentType);
        return meta;
    }

    /**
     * 上传文件到阿里云oss
     *
     * @param file            文件
     * @param fileName        文件名
     * @param endpoint        域名
     * @param accessKeyId     秘钥id
     * @param accessKeySecret 秘钥
     * @param bucketName      空间名
     * @return
     */
    public static Map<String, Object> upload(File file, String fileName, String endpoint, String accessKeyId, String accessKeySecret, String bucketName) {
        boolean result = true;
        Map<String, Object> data = new HashMap<>();
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            createBucket(ossClient, bucketName);
            ObjectMetadata meta = getContentType(fileName);
            if (meta != null) {
                PutObjectResult put = ossClient.putObject(new PutObjectRequest(bucketName, fileName, file, meta));
            } else {
                PutObjectResult put = ossClient.putObject(new PutObjectRequest(bucketName, fileName, file));
            }

            boolean exists = ossClient.doesObjectExist(bucketName, fileName);
            System.out.println("Does object " + bucketName + " exist? " + exists + "\n");
            if (!exists) {
                result = false;
            }

            ossClient.setObjectAcl(bucketName, fileName, CannedAccessControlList.PublicRead);

        } catch (OSSException oe) {
            oe.printStackTrace();
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message: " + oe.getErrorCode());
            System.out.println("Error Code:       " + oe.getErrorCode());
            System.out.println("Request ID:      " + oe.getRequestId());
            System.out.println("Host ID:           " + oe.getHostId());
            data.put("uploadErr", oe.toString());
            result = false;
        } catch (ClientException ce) {
            ce.printStackTrace();
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message: " + ce.getMessage());
            data.put("uploadErr", ce.toString());
            result = false;
        } finally {
            ossClient.shutdown();
        }
        data.put("result", result);
        return data;
    }

    /**
     * 上传文件并设置权限
     * @param file
     * @param objectName
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param bucketName
     * @param cannedACL 如果为null默认为private类型
     * @return
     */
    @Comment("上传文件并设置权限")
    public static boolean putObjectAcl(@Comment("File文件源")File file, @Comment("oss的object name")String objectName,
                                       @Comment("endpoint")String endpoint, @Comment("accessKeyId")String accessKeyId, @Comment("accessKeySecret")String accessKeySecret,
                                       @Comment("bucketName")String bucketName,@Comment("CannedAccessControlList枚举，缺省值null为私有模式")CannedAccessControlList cannedACL) {
        boolean result = true;
        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            createBucket(ossClient, bucketName);
            ObjectMetadata meta = getContentType(objectName);
            if (meta != null) {
                ossClient.putObject(new PutObjectRequest(bucketName, objectName, file, meta));
            } else {
                ossClient.putObject(new PutObjectRequest(bucketName, objectName, file));
            }

            boolean exists = ossClient.doesObjectExist(bucketName, objectName);

            if (!exists) {
                result = false;
            }

            ossClient.setObjectAcl(bucketName, objectName, cannedACL == null ? CannedAccessControlList.Private : cannedACL);

        } catch (OSSException oe) {
            log.error("阿里云oss putObjectAcl 错误：",oe);
            result = false;
        } catch (ClientException ce) {
            log.error("阿里云oss putObjectAcl 错误：",ce);
            result = false;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return result;
    }

    /**
     * 生成外链
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param bucketName
     * @param objectName
     * @param expiredHour 过期时间，小时
     * @return
     */
    public static String generatePresignedUrl(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,String objectName,int expiredHour) {

        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            // 设置签名URL过期时间，单位为毫秒。本示例以设置过期时间为1小时为例。
            Date expiration = new Date(new Date().getTime() + (expiredHour * 3600 * 1000L));
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            return url.toString();
        } catch (ClientException e) {
            log.error("阿里云oss生成外链错误：",e);
            return null;
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
    public static boolean deleteObject(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,String objectName) {

        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            ossClient.deleteObject(bucketName, objectName);
            return true;
        } catch (ClientException e) {
            log.error("阿里云oss生成外链错误：",e);
            return false;
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
    public static boolean doesObjectExist(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,String objectName) {

        OSS ossClient = null;
        try {
            ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
            return ossClient.doesObjectExist(bucketName, objectName);
        } catch (ClientException e) {
            log.error("阿里云oss生成外链错误：",e);
            return false;
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 创建bucket
     */
    private static void createBucket(OSS ossClient, String bucketName) {
        if (ossClient != null) {
            if (!ossClient.doesBucketExist(bucketName)) {
                System.out.println("Creating bucket " + bucketName + "\n");
                ossClient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossClient.createBucket(createBucketRequest);
            }
        }
    }

    public static String getBucketDomain(String bucketName, String endpointServer) {
        String bucketDomain = PROTOCOL_STR + bucketName + "." + endpointServer + "/";
        return bucketDomain;
    }
}
